using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Services;

namespace Microsoft.WowAddonStudio.FrameXml.Design.Serialization
{
	/// <summary>
	/// 
	/// </summary>
	public class FrameXmlRuntimeSerializer : IFrameXmlSerializer
	{
		private XmlSerializer serializer;

		#region IFrameXmlSerializer Members

		/// <summary>
		/// Deserializes the specified control.
		/// </summary>
		/// <param name="frameXml">The frameXml.</param>
		/// <param name="objectType">Type of the object.</param>
		/// <returns></returns>
		public object Deserialize(string frameXml, Type objectType)
		{
			serializer = new XmlSerializer(objectType);

			using (var xmlReader = XmlReader.Create(new StringReader(frameXml), CreateXmlReaderSettings()))
			{
				return serializer.Deserialize(xmlReader);
			}
		}

		/// <summary>
		/// Serializes the specified control.
		/// </summary>
		/// <param name="frame">The frame.</param>
		/// <returns></returns>
		public string Serialize(object frame)
		{
			if (frame == null)
				throw new ArgumentNullException("frame");


			var inheritableObject = frame as InheritableObject;

			inheritableObject.InheritanceEnabled = false;

			var frameXmlBuilder = new StringBuilder();
			
			serializer = new XmlSerializer(frame.GetType());

			using (XmlWriter writer = XmlWriter.Create(frameXmlBuilder, CreateXmlWriterSettings()))
			{
				serializer.Serialize(writer, frame);
			}
			inheritableObject.InheritanceEnabled = true;

			return frameXmlBuilder.ToString();
		}

		#endregion

		/// <summary>
		/// Creates the XML writer settings.
		/// </summary>
		/// <returns></returns>
		private static XmlWriterSettings CreateXmlWriterSettings()
		{
			return new XmlWriterSettings
			{
				Indent = true,
				IndentChars = "\t",
				OmitXmlDeclaration = true
			};
		}

		/// <summary>
		/// Creates <see cref="XmlReaderSettings"/> for reading FrameXML files.
		/// </summary>
		/// <returns>An instance of the <see cref="XmlReaderSettings"/> class.</returns>
		private static XmlReaderSettings CreateXmlReaderSettings()
		{
			var xmlReaderSettings = new XmlReaderSettings
			{
				IgnoreComments = true,
				ValidationType = ValidationType.None,
				IgnoreProcessingInstructions = true
			};

			return xmlReaderSettings;
		}
	}
}